﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MIMSDomain.Abstract;
using MIMSDomain.Entities;
using Moq;

namespace MIMSUnitTests.Domain
{
    [TestClass]
    public class EFNextOfKinRepositoryTests
    {
        public readonly IRepository<NextOfKin> MockNextOfKinRepository;

         public EFNextOfKinRepositoryTests()
        {
            //Arrange
            var _NextOfKins = new List<NextOfKin>{
                new NextOfKin       {Id=1, FirstName ="Solomon1",MiddleName="P1",LastName="Lar1", Address="OTA1", Email="solomon1@gmail.com", Phone="7224281"},
                new NextOfKin{Id=2, FirstName ="Solomon2",MiddleName="P2",LastName="Lar2", Address="OTA2", Email="solomon2@gmail.com", Phone="7224282"},
                new NextOfKin{Id=3,FirstName ="Solomon3",MiddleName="P3",LastName="Lar3", Address="OTA3", Email="solomon3@gmail.com", Phone="7224283"},
                new NextOfKin{Id=4, FirstName ="Solomon4",MiddleName="P4",LastName="Lar4", Address="OTA4", Email="solomon4@gmail.com", Phone="7224284"}
            };

            //Mock the  Repository
            var target = new Mock<IRepository<NextOfKin>>();
            target.Setup(p => p.All).Returns(_NextOfKins.AsQueryable());

            target.Setup(p => p.GetById(It.IsAny<int>())).Returns((int i) =>
                _NextOfKins.Where(p => p.Id == i).Single());
            target.Setup(p => p.Save(It.IsAny<NextOfKin>())).Returns((NextOfKin obj) =>
                {
                    if (obj.Id.Equals(default(int)))
                    {
                        obj.Id = _NextOfKins.Count() + 1;
                        _NextOfKins.Add(obj);
                    }
                    else
                    {
                        var original = _NextOfKins.Where(p => p.Id == obj.Id).Single();
                        if (original == null)
                        {
                            return false;
                        }
                        original.FirstName = obj.FirstName;
                        original.MiddleName = obj.MiddleName;
                        original.LastName = obj.LastName;
                        original.Phone = obj.Phone;
                        original.Address = obj.Address;
                        original.Email = obj.Email;
                        
                    }
                    return true;
                });
            target.Setup(p => p.Delete(It.IsAny<NextOfKin>())).Returns((NextOfKin obj) =>
                {

                    if (_NextOfKins.Contains(obj))
                    {
                        _NextOfKins.Remove(obj);
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                });
            
            MockNextOfKinRepository = target.Object;
        }
        
        [TestMethod]
        public void CanSave()
        {
            //Arrange
            var count = MockNextOfKinRepository.All.Count();
            //Assert
            Assert.AreEqual(4, count); //Confirm  count
            //Act
            var expected = MockNextOfKinRepository.Save(new NextOfKin {FirstName ="Solomon4",MiddleName="P4",LastName="Lar4", Address="OTA4", Email="solomon4@gmail.com", Phone="7224284"});

            //Assert
            count = MockNextOfKinRepository.All.Count();
            Assert.AreEqual(5, count); //Confirm  count after saving

        }

        [TestMethod]
        public void CannotAddDuplicate()
        {
            //Arrange
            var count = MockNextOfKinRepository.All.Count();
            //Assert
            Assert.AreEqual(4, count); //Confirm  count
            //Act
           var expected = MockNextOfKinRepository.Save( new NextOfKin       {Id=1, FirstName ="Solomon4",MiddleName="P4",LastName="Lar4", Address="OTA4", Email="solomon4@gmail.com", Phone="7224284"});

            //Assert
            count = MockNextOfKinRepository.All.Count();
            Assert.AreEqual(5, count); //Confirm  count after saving
        }

        [TestMethod]
        public void CanGetById()
        {
            //Act
            var expected = MockNextOfKinRepository.GetById(3);
            //Assert
            Assert.IsNotNull(expected);
            Assert.IsInstanceOfType(expected, typeof(NextOfKin));
            Assert.AreEqual(expected.Email, "solomon3@gmail.com");
        }

        [TestMethod]
        public void CanGetAll()
        {
            //Act
            var expected = MockNextOfKinRepository.All;
            //Assert
            Assert.IsNotNull(expected);
            Assert.IsInstanceOfType(expected, typeof(IQueryable<NextOfKin>));
            Assert.AreEqual(expected.Count(), 4);
        }

        [TestMethod]
        public void CanDelete()
        {
            //Arrange
            var count = MockNextOfKinRepository.All.Count();
            Assert.AreEqual(4, count);
            var objAllergy = MockNextOfKinRepository.GetById(3);
            Assert.IsInstanceOfType(objAllergy, typeof(NextOfKin));
            //Act
            MockNextOfKinRepository.Delete(objAllergy);
            count = MockNextOfKinRepository.All.Count();
            //Assert
            Assert.AreEqual(3, count);
        }
       
    }
}
